#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <pthread.h>

using namespace std;
//lesson38
// #define NUM 4
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;//宏定义锁
// int tickets=3000;//用多线程模拟抢票
// class threadData
// {
// public:
//     threadData(int number/*,pthread_mutex_t *mutex*/)
//     {
//         threadname="threadname-"+to_string(number);
//         //lock=mutex;
//     }
// public:
//     string threadname;
//     //pthread_mutex_t *lock;
// };
// // void* getTicket(void*args)
// // {
// //     threadData*td=static_cast<threadData*>(args);
// //     int cnt=5;
// //     while(cnt--)
// //     {
// //         cout<<td->threadname<<" is running "<<cnt<<endl;
// //         sleep(1);
// //     }
// //     return nullptr;
// // }
// void* getTicket(void*args)
// {
//     threadData*td=static_cast<threadData*>(args);
//     const char *name = td->threadname.c_str();
//     while(true)
//     {
//     //pthread_mutex_lock(td->lock);
//     pthread_mutex_lock(&lock);
//     if(tickets>0)
//     {
//         usleep(1000);//把 sleep(1) 放到 tickets-- 之前，让线程在判断票数有效后、修改票数前休眠，给其他线程留下更多竞争机会：
//         printf("who=%s, get a ticket: %d\n", name, tickets);
//         //cout<<td->threadname<<" get a ticket "<<tickets<<endl;//多线程不加锁cout容易混乱
//         tickets--;
//         //pthread_mutex_unlock(td->lock);
//         pthread_mutex_unlock(&lock);
//     }
//     else
//     {
//         //pthread_mutex_unlock(td->lock);
//         pthread_mutex_unlock(&lock);
//         break;
//     }
//     usleep(13);//休眠一下不然此时的线程最近，
//     //其他的还在阻塞容易造成此线程刚解锁重新抢占
//     }
//     return nullptr;
// }
// int main()
// {
//     //pthread_mutex_t lock;//定义锁或者宏
//     //pthread_mutex_init(&lock,nullptr);
//     vector<pthread_t> tids;
//     vector<threadData*> thread_datas;
//     for(int i=0;i<NUM;i++)
//     {
//         pthread_t tid;
//         threadData* td=new threadData(i/*,&lock*/);
//         thread_datas.push_back(td);
//         pthread_create(&tid,nullptr,getTicket,td);
//         tids.push_back(tid);
//     }
//     for (auto thread : tids)//等待每个子线程执行完成，保证子线程有足够时间输出内容
//     {
//         pthread_join(thread, nullptr);
//     }

//     for (auto td : thread_datas)//释放new出来的对象
//     {
//         delete td;
//     }
//     return 0;
// }

//多线程lesson37
//__thread int g_val = 100;//全局变量成为每个线程私有变量，只能定义内置类型
#define NUM 3 
int* p=nullptr;//全局证明主线程可以拿到其他线程数据
struct threadData
{
    string threadname;
};
string Tohex(pthread_t tid)
{
   char buffer[128];
    snprintf(buffer, sizeof(buffer), "0x%x", tid);//十六进制写进buffer
    return buffer; 
}
void* threadRoutine(void*args)//多线程共同执行一个函数
{
    int test_i=0;//验证每个线程有自己独立的栈
    int i=0;
    threadData *td=static_cast<threadData *>(args);//强转指针类型
    string tid=Tohex(pthread_self());
    int pid = getpid();
    if(td->threadname=="thread-2") p=&test_i;
    while(i<5)
    {
        printf("%s tid: %s,pid: %d\n",td->threadname.c_str(),tid.c_str(),pid);
        //cout << "tid: " << tid << ", pid: " << pid << endl;
        // cout<<"pid:"<<getpid()<<",tid:"
        // << Tohex(pthread_self())<<",threadname:"<<td->threadname<<endl;
        // <<",test_i:"<<test_i<<endl;
        sleep(1); //调度其他线程执行，此线程阻塞
        i++;
        test_i++;
    }
    return nullptr;
}
void InitThreadData(threadData *td, int number)
{
    td->threadname="thread-"+to_string(number);//thread_0
}
int main()
{
    vector<pthread_t> tids;
    for(int i=0;i<NUM;i++)
    {
        threadData *td=new threadData;//是指针指向堆内存
        pthread_t tid;
        InitThreadData(td,i);
        pthread_create(&tid,nullptr,threadRoutine,td);
        tids.push_back(tid);
        sleep(1);//创建一个线程休眠一秒
    }
    //cout<<"main thread get a thread local value,val:"<<*p<<",&val:"<<p<<endl;
    for(int i=0;i<NUM;i++)
    {
        pthread_join(tids[i],nullptr);//线程等待
    }
    return 0;
}
